<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>SMT元件库存管理系统</title>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script src="https://cdn.tailwindcss.com"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.0/papaparse.min.js"></script>
</head>
<body class="bg-white p-8">
  <div id="app"></div>

  <script>
    axios.defaults.baseURL = 'http://192.168.1.4/';

    const { createApp } = Vue;

    createApp({
      data() {
        return {
          parts: [],
          searchQuery: '',
          filteredParts: [],
          part: {
            nm: '', // Simplified from 'name'
            pk: '', // Simplified from 'package'
            qt: '', // Simplified from 'quantity'
            lc: '', // Simplified from 'location'
            mn: '', // Simplified from 'minimum stock level'
            pr: ''  // Simplified from 'price'
          },
          editPartIndex: null,
          showModal: false,
          isEditMode: false,
          notification: '',
          transactionType: 0, // 0 代表初始状态, 1 代表入库, 2 代表出库
          transactionQuantity: 0
        };
      },
      watch: {
        parts: {
          handler(newParts) {
            if (Array.isArray(newParts)) {
              this.filteredParts = newParts.filter(part => {
                return Object.entries(part).some(([key, value]) =>
                  key !== 'pr' && value && value.toString().toLowerCase().includes(this.searchQuery.toLowerCase())
                );
              });
            } else {
              console.error('newParts is not an array:', newParts);
            }
          },
          deep: true,
          immediate: true
        },
        searchQuery() {
          this.filteredParts = this.parts.filter(part =>
            Object.entries(part).some(([key, value]) =>
              key !== 'pr' && value && value.toString().toLowerCase().includes(this.searchQuery.toLowerCase())
            )
          );
        }
      },
      methods: {
        showNotification(message) {
          this.notification = message;
          setTimeout(() => {
            this.notification = '';
          }, 3000); // Hide notification after 3 seconds
        },
        async fetchParts() {
          try {
            const response = await axios.get('/inventory');
            // Assuming the response data is a string of concatenated JSON objects
            const dataString = response.data;
            const jsonString = `[${dataString.replace(/}\s*{/g, '},{')}]`;
            console.log('Converted JSON string:', jsonString); // 打印查看转化后的json格式是否正确
            this.parts = JSON.parse(jsonString);
            console.log('Fetched parts:', this.parts);
          } catch (error) {
            console.error('Failed to fetch parts:', error);
          }
        },
        searchParts() {
          console.log('Searching for:', this.searchQuery);
        },
        async addPart() {
          try {
            console.log(this.part);
            const response = await axios.post('/inventory', this.part);
            if (response.data && response.data.id) {
              this.parts.push(response.data);
              this.part = { nm: '', pk: '', qt: '', lc: '', mn: '', pr: '' }; // 重置单价字段
              this.showModal = false;
              // Add feedback
              console.log('元件添加成功！');
              this.showNotification('元件添加成功！');
              // Refresh the list
              await this.fetchParts();
            } else {
              throw new Error('保存的内容为空');
            }
          } catch (error) {
            console.error('Failed to add part:', error);
            alert('添加元件失败，请重试。');
          }
        },
        editPart(index) {
          const originalIndex = this.parts.findIndex(part => part.id === this.filteredParts[index].id);
          this.editPartIndex = originalIndex;
          this.part = { ...this.parts[originalIndex] };
          this.isEditMode = true;
          this.showModal = true;
          this.transactionType = 0; // 设置为初始状态
        },
        async updatePart() {
          try {
            const response = await axios.put(`/inventory/${this.parts[this.editPartIndex].id}`, this.part);
            if (response.status === 200) {
              this.part = { nm: '', pk: '', qt: '', lc: '', mn: '', pr: '' }; // 重置单价字段
              this.showModal = false;
              this.isEditMode = false;
              // Add feedback
              console.log('元件更新成功！');
              this.showNotification('元件更新成功！');
              // Refresh the list
              await this.fetchParts();
            } else {
              throw new Error('Failed to update part');
            }
          } catch (error) {
            console.error('Failed to update part:', error);
            alert('更新元件失败，请重试。');
          }
        },
        async deletePart(index) {
          const part = this.parts[index];
          if (confirm(`确定要删除元件 ${part.nm} 吗？`)) {
            try {
              await axios.delete(`/inventory/${part.id}`);
              this.parts.splice(index, 1);
              this.showNotification('元件删除成功！');
              console.log('元件删除成功！');
            } catch (error) {
              console.error('Failed to delete part:', error);
              alert('删除元件失败，请重试。');
            }
          }
        },
        openAddPartModal() {
          this.isEditMode = false;
          this.part = { nm: '', pk: '', qt: '', lc: '', mn: '', pr: '' }; // 重置单价字段
          this.showModal = true;
          this.transactionType = 0; // 设置为初始状态
        },
        closeModal() {
          this.showModal = false;
          this.isEditMode = false;
          this.part = { nm: '', pk: '', qt: '', lc: '', mn: '', pr: '' }; // 重置单价字段
          this.transactionType = 0; // 设置为初始状态
        },
        importCsv() {
          if (confirm('确认覆盖全部数据？')) {
            document.getElementById('upload').click();
            document.getElementById('upload').addEventListener('change', async (event) => {
              const file = event.target.files[0];
              Papa.parse(file, {
                header: true,
                complete: async (results) => {
                  const parts = results.data
                    .filter(item => item.Name)  // Filter out items with empty name
                    .map(item => ({
                      nm: item.Name,
                      pk: item.Footprint,
                      qt: parseInt(item.Quantity, 10),
                      lc: item.Location,
                      mn: item.MinStock,
                      pr: parseFloat(item.Price)
                    }));
                  try {
                    const response = await axios.post('/inventory/batch', parts);
                    if (response.status === 200) {
                      this.showNotification('元件批量添加成功！');
                      console.log('元件批量添加成功！', parts);
                      await this.fetchParts();
                    } else {
                      throw new Error('Failed to add parts');
                    }
                  } catch (error) {
                    console.error('Failed to add parts:', error);
                    alert('批量添加元件失败，请重试。');
                  }
                }
              });
            }, { once: true });
          }
        },
        exportCsv() {
          const csvData = this.parts.map(part => ({
            Name: part.nm,
            Footprint: part.pk,
            Location:part.lc,
            Quantity: part.qt,
            MinStock:part.mn,
            Price: part.pr
          }));

          const csv = Papa.unparse(csvData);
          const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
          const link = document.createElement('a');
          const url = URL.createObjectURL(blob);
          link.setAttribute('href', url);
          link.setAttribute('download', 'parts_inventory.csv');
          link.style.visibility = 'hidden';
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
        },
        openTransactionModal(index, type) {
          this.editPartIndex = index;
          this.transactionType = type;
          this.transactionQuantity = 0;
          this.part = { ...this.parts[index] }; // 填充part对象
          this.showModal = true;
        },
        async saveTransaction() {
           this.part = { ...this.parts[this.editPartIndex] };
          const originalQuantity = parseInt(this.part.qt);
          console.log('Original Quantity:', originalQuantity);
          console.log('Transaction Type:', this.transactionType);
          console.log('Transaction Quantity:', this.transactionQuantity);
          if (this.transactionType === 1) {
            this.part.qt = (originalQuantity + parseInt(this.transactionQuantity)); // Addition for incoming stock
          } else if (this.transactionType === 2) {
            if (originalQuantity < parseInt(this.transactionQuantity)) {
              alert('库存不够');
              return;
            }
            this.part.qt = (originalQuantity - parseInt(this.transactionQuantity)); // Subtraction for outgoing stock
          }
          console.log('Updated Part:', this.part);
          await this.updatePart();
        }
      },
      mounted() {
        this.fetchParts();
      },
      template: `
        <div class="container mx-auto py-8">
          <h1 class="text-2xl font-semibold mb-4">SMT元件库存管理系统</h1>
          <p class="text-sm text-gray-500 mb-6">制作者: <a href="https://space.bilibili.com/28249524" class="text-blue-500 hover:underline">ideaswork</a></p>
          <div class="absolute top-0 right-0 p-4">
            <a href="https://gitee.com/ideaswork/esp32-micropython" class="text-blue-500 hover:underline">项目开源链接</a>
          </div>

          <input type="file" id="upload" accept=".csv" style="display: none;" />

          <!-- Search Bar -->
          <div class="flex items-center gap-2 mb-4">
            <input
              v-model="searchQuery"
              type="text"
              placeholder="搜索元件..."
              class="border border-gray-300 rounded-lg px-4 py-2 w-full sm:w-1/3 focus:outline-none focus:ring-2 focus:ring-gray-300"
            />
            <button
              @click="searchParts"
              class="bg-gray-700 text-white px-4 py-2 rounded-lg hover:bg-gray-800"
            >
              搜索
            </button>
          </div>

          <!-- Toolbar -->
          <div class="flex justify-end gap-2 mb-6">
            <button
              class="bg-green-500 text-white px-4 py-2 rounded-lg hover:bg-green-600"
              @click="openAddPartModal"
            >
              添加元件
            </button>
            <button
              @click="exportCsv"
              class="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700"
            >
              导出CSV
            </button>
            <button
              @click="importCsv"
              class="bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600"
            >
              导入CSV
            </button>
          </div>

          <!-- Table Section -->
          <div class="overflow-x-auto">
            <table class="w-full border-collapse border border-gray-300 rounded-lg">
              <thead class="bg-gray-100 text-left">
                <tr>
                  <th class="border-b px-4 py-3 font-medium">名称</th>
                  <th class="border-b px-4 py-3 font-medium">封装</th>
                  <th class="border-b px-4 py-3 font-medium">数量</th>
                  <th class="border-b px-4 py-3 font-medium">位置</th>
                  <th class="border-b px-4 py-3 font-medium">预警值</th>
                  <th class="border-b px-4 py-3 font-medium hidden sm:table-cell">单价</th> <!-- 手机端隐藏单价 -->
                  <th class="border-b px-4 py-3 font-medium">操作</th>
                </tr>
              </thead>
              <tbody>
                <tr
                  v-for="(part, index) in filteredParts"
                  :key="index"
                  :class="{'bg-red-100': part.qt <= part.mn, 'hover:bg-gray-50': part.qt > part.mn}"
                >
                  <td class="px-4 py-3">{{ part.nm }}</td>
                  <td class="px-4 py-3">{{ part.pk }}</td>
                  <td class="px-4 py-3">{{ part.qt }}</td>
                  <td class="px-4 py-3">{{ part.lc }}</td>
                  <td class="px-4 py-3">{{ part.mn }}</td>
                  <td class="px-4 py-3 hidden sm:table-cell">{{ part.pr }}</td> <!-- 手机端隐藏单价 -->
                  <td class="px-4 py-3 flex gap-2">
                    <button @click="editPart(index)" class="text-blue-500">
                      编辑
                    </button>
                
                    <button @click="openTransactionModal(index, 1)" class="text-green-500">
                      入库
                    </button>
                    <button @click="openTransactionModal(index, 2)" class="text-yellow-500">
                      出库
                    </button>
                    
                    <button @click="deletePart(index)" class="text-red-500">
                      删除
                    </button>
                  </td>
                </tr>
                <tr v-if="filteredParts.length === 0">
                  <td colspan="7" class="text-center py-4">没有数据</td>
                </tr>
              </tbody>
            </table>
          </div>

          <!-- Modal -->
          <div
            v-if="showModal"
            class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"
          >
            <div class="bg-white p-6 rounded-lg shadow-lg w-full sm:w-1/2">
              <h2 class="text-xl font-semibold mb-4">
                {{ isEditMode ? '编辑元件' : transactionType === 1 ? '入库' : transactionType === 2 ? '出库' : '添加元件' }}
              </h2>
              <div v-if="isEditMode || transactionType === 0" class="flex flex-col gap-4 mb-6">
                <div class="flex gap-4">
                  <input
                    v-model="part.nm"
                    type="text"
                    placeholder="名称"
                    class="border border-gray-300 rounded-lg px-4 py-2 w-full"
                  />
                  <input
                    v-model="part.pk"
                    type="text"
                    placeholder="封装"
                    class="border border-gray-300 rounded-lg px-4 py-2 w-full"
                  />
                </div>
                <div class="flex gap-4">
                  <input
                    v-model="part.pr"
                    type="number"
                    placeholder="单价"
                    class="border border-gray-300 rounded-lg px-4 py-2 w-full"
                  />
                  <input
                    v-model="part.lc"
                    type="text"
                    placeholder="位置"
                    class="border border-gray-300 rounded-lg px-4 py-2 w-full"
                  />
                </div>
                <div class="flex gap-4">
                  <input
                    v-model="part.qt"
                    type="number"
                    placeholder="数量"
                    class="border border-gray-300 rounded-lg px-4 py-2 w-full"
                  />
                  <input
                    v-model="part.mn"
                    type="number"
                    placeholder="库存预警值"
                    class="border border-gray-300 rounded-lg px-4 py-2 w-full"
                  />
                </div>
              </div>
              <div v-else class="flex flex-col gap-4 mb-6">
                <div class="grid grid-cols-2 gap-4">
                  <div>名称: {{ part.nm }}</div>
                  <div>封装: {{ part.pk }}</div>
                  <div>单价: {{ part.pr }}</div>
                  <div>位置: {{ part.lc }}</div>
                  <div>数量: {{ part.qt }}</div>
                  <div>库存预警值: {{ part.mn }}</div>
                </div>
                <label :for="transactionType === 1 ? '入库数量' : '出库数量'" class="block text-gray-700">数量</label>
                <input
                  v-model="transactionQuantity"
                  type="number"
                  :placeholder="transactionType === 1 ? '入库数量' : '出库数量'"
                  :id="transactionType === 1 ? '入库数量' : '出库数量'"
                  class="border border-gray-300 rounded-lg px-4 py-2 w-full"
                />
              </div>
              <div class="flex justify-end gap-2">
                <button
                  @click="isEditMode ? updatePart() : saveTransaction()"
                  class="bg-blue-500 text-white px-4 py-2 rounded-lg hover:bg-blue-600"
                >
                  {{ isEditMode ? '保存' : '确认' }}
                </button>
                <button
                  @click="closeModal"
                  class="bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600"
                >
                  取消
                </button>
              </div>
            </div>
          </div>

          <!-- Notification -->
          <div
            v-if="notification"
            class="fixed top-0 inset-x-0 bg-green-500 text-white text-center py-2"
          >
            {{ notification }}
          </div>
        </div>
      `,
    }).mount('#app');
  </script>
</body>
</html>
